import AsyncValidator from 'async-validator';

import { isFunction, isPromise } from '@/utils/validate/data';

// const validate = (model, rules, callback, options) => {
// 	const initOptions = {
// 		showMessage: true
// 	};
// 	options = Object.assign({}, initOptions, options || {});
// 	// 如果需要验证的fields为空，调用验证时立刻返回callback
// 	if ((!rules || rules.length === 0) && callback) {
// 		callback(true, null);
// 	}
// 	let errors = [];
// 	const props = Object.keys(rules);
// 	for (let i in props) {
// 		const prop = props[i];
// 		const value = utils.getValueByProp(model, prop);
// 		utils.validateItem(rules, prop, value, err => {
// 			if (err && err.length > 0) {
// 				errors = errors.concat(err);
// 			}
// 		});
// 	}
// 	if (errors.length > 0) {
// 		if (options.showMessage) {
// 			utils.showToast(errors[0].message);
// 		}
// 		callback(false, errors);
// 	} else {
// 		callback(true, null);
// 	}
// };
// const validateField = (model, rules, props, callback, options) => {
// 	const initOptions = {
// 		showMessage: true
// 	};
// 	options = Object.assign({}, initOptions, options || {});
// 	props = [].concat(props);
// 	if (props.length === 0) {
// 		return;
// 	}
// 	let errors = [];
// 	for (let i in props) {
// 		const prop = props[i];
// 		const value = utils.getValueByProp(model, prop);
// 		utils.validateItem(rules, prop, value, err => {
// 			if (err && err.length > 0) {
// 				errors = errors.concat(err);
// 			}
// 		});
// 	}
// 	if (errors.length > 0) {
// 		if (options.showMessage) {
// 			utils.showToast(errors[0].message);
// 		}
// 		callback(false, errors);
// 	} else {
// 		callback(true, null);
// 	}
// };
// const validateItem = (rules, prop, value, callback) => {
// 	if (!rules || JSON.stringify(rules) === '{}') {
// 		if (callback instanceof Function) {
// 			callback();
// 		}
// 		return true;
// 	}
// 	const propRules = [].concat(rules[prop] || []);
// 	const descriptor = {
// 		[prop]: propRules
// 	};
// 	const validator = new AsyncValidator(descriptor);
// 	const model = {
// 		[prop]: value
// 	};
// 	validator.validate(
// 		model,
// 		{
// 			firstFields: true
// 		},
// 		errors => {
// 			callback(errors);
// 		}
// 	);
// };
// const getValueByProp = (obj, prop) => {
// 	let tempObj = obj;
// 	prop = prop.replace(/\[(\w+)\]/g, '.$1').replace(/^\./, '');
// 	let keyArr = prop.split('.');
// 	let i = 0;
// 	for (let len = keyArr.length; i < len - 1; ++i) {
// 		if (!tempObj) break;
// 		let key = keyArr[i];
// 		if (key in tempObj) {
// 			tempObj = tempObj[key];
// 		} else {
// 			break;
// 		}
// 	}
// 	return tempObj ? (typeof tempObj[keyArr[i]] === 'string' ? tempObj[keyArr[i]].trim() : tempObj[keyArr[i]]) : null;
// };

const isEmptyValue = value => {
	if (Array.isArray(value)) {
		return !value.length;
	}

	return !value;
};

export const fieldMixins = {
	methods: {
		/**
		 *  处理自定义校验方法校验
		 *  <ui-field :rules="[ { validator , message , trigger }]"></ui-field>
		 */
		runValidator(value, rule) {
			return new Promise(resolve => {
				// 执行用户的自定义校验方法
				const returnVal = rule.validator(value, rule);
				// 返回值可以是 promise 那么就可以是异步校验的方式 如后台校验等
				if (isPromise(returnVal)) {
					return returnVal.then(resolve);
				}

				resolve(returnVal);
			});
		},
		/**
		 * 是否是同步校验的方式
		 *
		 * <ui-field :rules="[ { required , message , trigger }]"></ui-field>
		 * <ui-field :rules="[ { pattern : '/^1\d{10}/' , message , trigger }]"></ui-field>
		 */
		runSyncRule(value, rule) {
			// 如果定义了 required 且值为空 那么直接出发 校验错误结果
			if (rule.required && isEmptyValue(value)) {
				return false;
			}
			// 如果定义了 正则校验的方式  那么直接使用正则校验
			if (rule.pattern && !rule.pattern.test(value)) {
				return false;
			}
			return true;
		},

		/**
		 * 获取校验规则上的message的提示消息
		 *
		 * @param {*} value
		 * @param {*} rule
		 * @returns
		 */
		getRuleMessage(value, rule) {
			const { message } = rule;
			// 支持 message也是函数 而不是普通的消息字符串
			if (isFunction(message)) {
				return message(value, rule);
			}

			return message;
		},

		/**
		 * 执行指定校验规则的校验
		 */
		runRules(rules) {
			// rules 是一个数组，那么就依次去执行每一个校验规则
			return rules.reduce(
				(promise, rule) =>
					promise.then(() => {
						
						// 如果已经存在错误的校验结果 那么就不需要继续下面的校验了
						// 当然这种也会存在如果对某一个项点击触发了一次校验 如果没有设置 blur等  那么下次校验就会过滤 需要重置校验结果
						if (this.validateMessage) {
							return;
						}
						// 校验的值
						let value = this.value;
						// 是否定义了 输入项格式化方法 ，那么会先对值进行格式化，再进行校验
						if (rule.formatter) {
							value = rule.formatter(value, rule);
						}
						// 是否是同步校验，那么直接出发同步校验 ( required pattern 优先于 validator)
						if (!this.runSyncRule(value, rule)) {
							this.validateMessage = this.getRuleMessage(value, rule);
							return;
						}
						// 自定义校验函数(可以是 异步校验)
						if (rule.validator) {
							return this.runValidator(value, rule).then(result => {
								if (result === false) {
									this.validateMessage = this.getRuleMessage(value, rule);
								}
							});
						}
					}),
				Promise.resolve()
			);
		},

		/**
		 * 触发当前field的校验
		 *
		 * @param {*} [rules=this.rules] 校验规则 默认为 用户设置的校验规则  <ui-field :rules="[ { validator , message , trigger }]"></ui-field>
		 * @returns
		 */
		validate(rules = this.rules) {
			return new Promise(resolve => {
        debugger;
				if (!rules) {
					resolve();
				}

				this.runRules(rules).then(() => {
					// 支持name 去区分form中每一个错误消息属于谁
					if (this.validateMessage) {
						resolve({
							name: this.name,
							message: this.validateMessage
						});
					} else {
						resolve();
					}
				});
			});
		},

		/**
		 * field发起校验
		 *  发起制定触发校验的rule校验方法
		 *  如
		 *    我们在onBlur中出触发 validateWithTrigger('onBlur') 那么这时候 rules里面只有设置了 trigger 且 trigger为 'onBlur' 的校验规则才会触发
		 *
		 * @params { String } trigger 校验的触发方法  'onBlur'
		 *
		 */
		validateWithTrigger(trigger) {
			// 需要在 form 元素里面 且当前field定义了 rules
			if (this.uiform && this.rules) {
				// 获取 form元素中定义的默认触发校验方式
				const defaultTrigger = this.uiform.validateTrigger === trigger;
				// 过滤掉自定义rule中 不是当前校验trigger的校验方法
				const rules = this.rules.filter(rule => {
					if (rule.trigger) {
						return rule.trigger === trigger;
					}
					return defaultTrigger;
				});
				// 用过滤号的校验规则去校验当前值
				this.validate(rules);
			}
		},

		resetValidation() {
			if (this.validateMessage) {
				this.validateMessage = '';
			}
		}

		// validate(){

		//   return new Promise( (resolve , reject) => {

		//   })
		// }
	}
};

export const formMixins = {
	methods: {
		validate(callback) {
			validate(this.model, this.rules, callback, {
				showMessage: this.showMessage
			});
		},
		validateField(props, callback) {
			validateField(this.model, this.rules, props, callback, {
				showMessage: this.showMessage
			});
		}
	}
};
